package net.oschina.git.fsppp.view.frame;

import net.oschina.git.fsppp.common.base.BaseEvent;
import net.oschina.git.fsppp.common.cmd.Command;
import net.oschina.git.fsppp.model.P3Dir;
import net.oschina.git.fsppp.common.base.BaseFrame;
import net.oschina.git.fsppp.view.contract.FileOPContract;
import net.oschina.git.fsppp.widget.MyListCellRenderer;
import net.oschina.git.fsppp.view.model.FileModel;
import net.oschina.git.fsppp.view.presneter.FilePresenter;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by Qi_Huang on 2016/9/24.
 */
public class FileOpView extends BaseFrame<FileOPContract.Presenter, FileOPContract.Model>
        implements FileOPContract.View, ActionListener{
    private JMenuBar menuBar;
    private JMenu item1, item2, item3;
    private JMenuItem cItem1, cItem2, cItem3, cItem4, cItem5;
    private JMenuItem cItem6, cItem7, cItem8;
    private JMenuItem cItem9;
    private JScrollPane fileScrollPanel;
    private JPanel infoPanel, filePanel, diskPanel;
    private JPopupMenu pM_normal, pM_file;
    private JMenuItem popItem1, popItem2, popItem3, popItem0;
    private JMenuItem popItem4, popItem5, popItem6, popItem7;
    private JLabel pathLabel, consoleLabel, diskLabel;
    private JTextField pathField, searchField, consoleField;
    private JButton search, back, ahead;
    private JButton[] diskBtns;
    private JList<P3Dir> fileList;
    private DefaultListModel<P3Dir> model, diskModel;
    private MyListCellRenderer cellRenderer;
    private JList<P3Dir> diskList;
    /**
     * 当前文件（夹）列表
     */
    private List<P3Dir> p3Dirs, diskDirs;

    /**
     * 当前文件列表索引
     */
    private int currentFileIndex = 0;

    /**
     * 当前选中项类型
     */
    private int currentFileType = 0;

    /**
     * 当前文件目录路径
     */
    private String currentPath;

    /**
     * 文件类型
     */
    private final static int FILE = P3Dir.TYPE_OF_FILE;
    private final static int DIR = P3Dir.TYPE_OF_DIR;

    /**
     * 访问路径栈及当前索引
     */
    private List<String> pathStack;
    private int pathIndex;

    /**
     * 文件分配表
     */
    private Byte[] fatBytes;

    /**
     * 手动输入的路径
     */
    private String inputPath;

    public static void main(String[] args) {
        try {
            String lookAndFeel = UIManager.getSystemLookAndFeelClassName();
            UIManager.setLookAndFeel(lookAndFeel);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
        new FileOpView();
    }

    @Override
    public void initPM() {
        mModel = new FileModel();
        mPresenter = new FilePresenter(this, mModel);
        p3Dirs = new ArrayList<>();
        cellRenderer = new MyListCellRenderer();
        pathStack = new ArrayList<>();
        pathIndex = -1;
    }

    @Override
    public void initView() {
        menuBar = new JMenuBar();
        item1 = new JMenu("文件");
        item2 = new JMenu("目录");
        item3 = new JMenu("高级");
        item1.setEnabled(false);
        item2.setEnabled(false);
        menuBar.add(item1);
        menuBar.add(item2);
        menuBar.add(item3);

        cItem4 = new JMenuItem("重命名");
        cItem5 = new JMenuItem("删除");

        cItem7 = new JMenuItem("删除");
        cItem8 = new JMenuItem("重命名");

        cItem1 = new JMenuItem("格式化磁盘");

        item1.add(cItem5);
        item1.add(cItem4);

        item2.add(cItem7);
        item2.add(cItem8);

        item3.add(cItem1);

        back = new JButton(new ImageIcon(getClass().getResource("/image/back.png")));
        ahead = new JButton(new ImageIcon(getClass().getResource("/image/ahead.png")));
        back.setBounds(10, 10, 30, 25);
        ahead.setBounds(45, 10, 30, 25);

        pathLabel = new JLabel("当前路径：");
        pathLabel.setBounds(80, 10, 80, 25);
        pathField = new JTextField();
        pathField.setBounds(150, 10, 380, 25);

        searchField = new JTextField();
        searchField.setBounds(580, 10, 120, 25);

        search = new JButton("搜索");
        search.setBounds(710, 10, 70, 25);

        diskLabel = new JLabel("磁盘列表");
        diskLabel.setBounds(10, 52, 200, 25);
        consoleLabel = new JLabel("输入命令(help：查看帮助): ");
        consoleField = new JTextField();
        consoleLabel.setBounds(220, 50, 200, 25);
        consoleField.setBounds(420, 50, 300, 25);

        filePanel = new JPanel();
        filePanel.setBackground(Color.WHITE);
        filePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 35, 20));
        fileScrollPanel = new JScrollPane(filePanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        fileScrollPanel.setBounds(220, 77, 565, 380);
        fileScrollPanel.setBorder(BorderFactory.createEtchedBorder());

        model = new DefaultListModel<>();
        fileList = new JList<>(model);
        fileList.setFixedCellWidth(300);
        fileList.setCellRenderer(cellRenderer);
        fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        filePanel.add(fileList);


        diskPanel = new JPanel();
        diskPanel.setBackground(Color.WHITE);
//        diskPanel.setLayout(new FlowLayout(FlowLayout.TRAILING, 35, 20));
        diskPanel.setBounds(10, 77, 200, 380);
        diskPanel.setLayout(new GridLayout(6, 1, 10, 10));
        diskPanel.setBorder(BorderFactory.createEtchedBorder());

        diskModel = new DefaultListModel<>();

        diskList = new JList<>(model);
        diskList.setCellRenderer(new DefaultListCellRenderer());
        diskList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        infoPanel = new JPanel();
        infoPanel.setBounds(10, 460, 775, 170);
        infoPanel.setBorder(BorderFactory.createTitledBorder("文件分配表"));
        infoPanel.setBackground(Color.WHITE);
        infoPanel.setLayout(new GridLayout(8, 16, 0, 0));


        pM_normal = new JPopupMenu();
        popItem1 = new JMenuItem("新建文件");
        popItem2 = new JMenuItem("新建文件夹");
        pM_normal.add(popItem1);
        pM_normal.add(popItem2);


        pM_file = new JPopupMenu();
        popItem4 = new JMenuItem("删除");
        popItem6 = new JMenuItem("重命名");
        popItem3 = new JMenuItem("属性");
        pM_file.add(popItem4);
        pM_file.add(popItem6);
        pM_file.add(popItem3);

        this.add(back);
        this.add(ahead);
        this.add(diskLabel);
        this.add(consoleLabel);
        this.add(consoleField);
        this.add(fileScrollPanel);
        this.add(diskPanel);
        this.add(infoPanel);
        this.add(pathLabel);
        this.add(pathField);
        this.add(searchField);
        this.add(search);
        this.setJMenuBar(menuBar);
        this.setSize(NORMAL_WIDTH, NORMAL_HEIGHT);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLayout(null);
        mPresenter.initDisk();
    }

    @Override
    public void initListener() {
        back.addActionListener(this);
        ahead.addActionListener(this);
        search.addActionListener(this);
        cItem1.addActionListener(this);
        cItem4.addActionListener(this);
        cItem5.addActionListener(this);
        cItem7.addActionListener(this);
        cItem8.addActionListener(this);
        popItem1.addActionListener(this);
        popItem2.addActionListener(this);
        popItem3.addActionListener(this);
        popItem4.addActionListener(this);
        popItem6.addActionListener(this);
        for (int i = 0; i < diskBtns.length; i++) {
            final P3Dir dir = diskDirs.get(i);
            diskBtns[i].addActionListener(e -> {
                mPresenter.getChildDirs(dir);
                mPresenter.geFatList(dir.getName().substring(0, 1));
                currentPath = dir.getPath();
                increasePathStack();
                //选择任意磁盘后 才出现菜单
                fileScrollPanel.setComponentPopupMenu(pM_normal);
                fileList.setComponentPopupMenu(pM_file);
            });
        }
        diskBtns[0].doClick();
        fileList.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 1) {
                    currentFileIndex = fileList.getSelectedIndex();
                    P3Dir dir = p3Dirs.get(currentFileIndex);
                    currentFileType = dir.getType();
                    for (int i = 2; i < fatBytes.length; i++) {
                        if (fatBytes[i] != 0)
                            infoPanel.getComponent(i).setBackground(Color.orange);
                    }
                    infoPanel.updateUI();
                    if (currentFileType == FILE) {
                        item1.setEnabled(true);
                        item2.setEnabled(false);
                    } else {
                        item1.setEnabled(false);
                        item2.setEnabled(true);
                    }
                    mPresenter.getFileLink(dir);
                } else if (e.getClickCount() == 2) {
                    if (currentFileType == DIR) {
                        currentPath = fileList.getSelectedValue().getPath();
                        mPresenter.getChildDirs(p3Dirs.get(currentFileIndex));
                        increasePathStack();
                    } else {
                        //打开文件
                        openFile(false);
                    }
                }
            }
        });

        pathField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    inputPath = pathField.getText().trim();
                    mPresenter.getCurrentFile(inputPath);
                }
            }
        });

        consoleField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    String command = consoleField.getText();
                    execCommand(command);
                }
            }
        });
        fileList.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
                    goBack();
                }
            }
        });
    }

    private void openFile(boolean lock) {
        P3Dir dir = p3Dirs.get(currentFileIndex);
        if (lock) {
            dir.setIsOpen(true);
        }
        BaseEvent.getDefault().setParam(dir);
        new EditView(FileOpView.this);
    }


    @Override
    protected String getFrameTitle() {
        return "文件管理";
    }

    @Override
    public void returnCurrentFile(List<P3Dir> list) {
        p3Dirs = list;
        cellRenderer.onChange(p3Dirs);
        model.clear();
        p3Dirs.forEach(dir -> {
            model.addElement(dir);
        });
        if (list.size() != 0) {
            fileList.setSelectedIndex(0);
            currentFileIndex = 0;
        }
        refresh();
        //手动输入路径或是命令跳转时需要区别
        if (list.size() != 0) {
            String path = p3Dirs.get(0).getPath();
            String newPath = path.substring(0, path.lastIndexOf("\\") + 1);
            currentPath = newPath;
        } else {
            if (inputPath != null) {
                currentPath = inputPath;
                inputPath = null;
            }
        }
        pathField.setText(currentPath);
    }

    @Override
    public void returnNewDirOrFile(P3Dir dir) {
        p3Dirs.add(dir);
        cellRenderer.onChange(p3Dirs);
        model.addElement(dir);
        refresh();
        //创建文件（夹）成功 重绘分配表
        mPresenter.geFatList(currentPath.substring(0, 1));
    }

    @Override
    public void returnInitialDisk(final List<P3Dir> dirs) {
        diskBtns = new JButton[dirs.size()];
        diskDirs = dirs;
        for (int i = 0; i < diskBtns.length; i++) {
            P3Dir dir = dirs.get(i);
            String name = dir.getName();
            diskBtns[i] = new JButton("磁盘" + name);
            diskPanel.add(diskBtns[i]);
        }
        refresh();
    }

    @Override
    public void returnFatBytes(Byte[] fatBytes) {
        this.fatBytes = fatBytes;
        infoPanel.removeAll();
        for (int i = 0; i < fatBytes.length; i++) {
            JPanel p = new JPanel();
            if (i < 2) {
                p.setBackground(Color.decode("#FF4500"));
            } else {
                p.setBackground(fatBytes[i] == 0 ? Color.GRAY : Color.ORANGE);
            }
            p.setBorder(BorderFactory.createLineBorder(Color.WHITE));
            infoPanel.add(p);
        }
        refresh();
        infoPanel.updateUI();
    }

    @Override
    public void returnEditedFile(P3Dir dir) {
        p3Dirs.set(currentFileIndex, dir);
        model.set(currentFileIndex, dir);
        refresh();
        mPresenter.geFatList(currentPath.substring(0, 1));
        mPresenter.getFileLink(dir);
    }

    @Override
    public void returnDelResult(boolean isDeleted) {
        if (isDeleted) {
            p3Dirs.remove(currentFileIndex);
            cellRenderer.onChange(p3Dirs);
            model.remove(currentFileIndex);
            refresh();
            mPresenter.geFatList(currentPath.substring(0, 1));
        }
    }

    @Override
    public void returnFormatResult(boolean isFormated) {
        if (isFormated) {
            currentPath = "c:\\";
            diskBtns[0].doClick();
            showMsg("格式化完成！");
        }
    }

    @Override
    public void returnFileLink(LinkedList<Integer> linkedList) {
        if (linkedList == null) {
            P3Dir dir = p3Dirs.get(currentFileIndex);
            infoPanel.getComponent(dir.getStartNum()).setBackground(Color.CYAN);
        } else {
            linkedList.forEach(i -> {
                infoPanel.getComponent(i).setBackground(Color.CYAN);
            });
        }
    }

    @Override
    public void returnSearchResult(List<P3Dir> list) {
        p3Dirs = list;
        pathField.setText("搜索结果");
        cellRenderer.onChange(p3Dirs);
        model.clear();
        p3Dirs.forEach(dir -> model.addElement(dir));
        refresh();
    }


    @Override
    public void actionPerformed(ActionEvent e) {
        Object source = e.getSource();
        if (source == popItem1) {
            createNewDir(FILE);
        } else if (source == popItem2) {
            createNewDir(DIR);
        } else if (source == popItem6) {
            modifyFileName();
        } else if (source == back) {
            goBack();
        } else if (source == ahead) {
            goAhead();
        } else if (source == cItem4 || source == cItem8) {
            modifyFileName();
        } else if (source == cItem5
                || source == cItem7
                || source == popItem4) {
            deleteFile();
        } else if (e.getSource() == cItem1) {
            cleanDisk();
        } else if (source == popItem3) {
            BaseEvent.getDefault().setParam(p3Dirs.get(currentFileIndex));
            new PropertyView();
        } else if (source == search) {
            String name = searchField.getText().trim();
            if (name.equals("")) {
                showMsg("请输入正确的文件名！");
            } else {
                mPresenter.searchFile(currentPath, name);
            }
        }
    }

    private void cleanDisk() {
        String[] names = new String[diskDirs.size()];
        for (int i = 0; i < diskDirs.size(); i++) {
            names[i] = diskDirs.get(i).getName();
        }
        try {
            int index = showSelectDialog(names, "选择格式化的磁盘");
            String diskName = names[index].substring(0, 1);
            mPresenter.formatDisk(diskName);
        } catch (NullPointerException e) {
        }
    }

    private void deleteFile() {
        P3Dir dir = p3Dirs.get(currentFileIndex);
        int startNum = dir.getStartNum();
        int length = dir.getLength();
        int n = showComfirmDialog("确定删除[" + dir.getName() + "]?");
        if (n == JOptionPane.YES_OPTION) {
            mPresenter.deleteFile(dir);
        }
        for (int i = startNum; i < startNum + length; i++) {
            infoPanel.getComponent(i).setBackground(Color.GRAY);
        }
        infoPanel.updateUI();
    }

    private void goBack() {
        if (pathIndex <= 0) {
            return;
        }
        pathIndex--;
        currentPath = pathStack.get(pathIndex);
        mPresenter.getCurrentFile(currentPath);
        pathField.setText(currentPath);
    }

    private void goAhead() {
        if (pathIndex == -1 || pathIndex == pathStack.size() - 1) {
            return;
        }
        pathIndex++;
        currentPath = pathStack.get(pathIndex);
        mPresenter.getCurrentFile(currentPath);
        pathField.setText(currentPath);
    }

    private void increasePathStack() {
        pathField.setText(currentPath);
        if (pathIndex != -1 && currentPath.equals(pathStack.get(pathIndex))) {
            return;
        }
        if (++pathIndex <= pathStack.size() - 1) {
            String oldPath = pathStack.get(pathIndex);
            if (oldPath != null) {
                if (currentPath.equals(oldPath)) {
                    return;
                }
                pathStack.set(pathIndex, currentPath);
                for (int i = pathIndex + 1, p = pathStack.size(); i < p; i++) {
                    pathStack.set(i, null);
                }
                while (pathStack.contains(null)) {
                    pathStack.remove(null);
                }
            }
        } else {
            pathStack.add(currentPath);
        }
    }

    private void createNewDir(int type) {
        String name = showInputDialog("");
        if (name == null) {
            return;
        } else if (name.trim().equals("")) {
            showMsg("名称不为空");
        } else  {
            if (type == FILE) {
                mPresenter.createNewFile(currentPath.trim(), name);
            } else {
                mPresenter.createNewDir(currentPath.trim(), name);
            }
        }
    }

    private void modifyFileName() {
        String name = showInputDialog(p3Dirs.get(currentFileIndex).getName());
        if (name == null) {
            return;
        } else if (name.trim().equals("")) {
            showMsg("名称不为空");
        } else {
            try {
                P3Dir dir = (P3Dir) p3Dirs.get(currentFileIndex).clone();
                dir.setName(name);
                mPresenter.editFile(dir);
            } catch (CloneNotSupportedException e1) {
                e1.printStackTrace();
            }
        }
    }

    @Override
    public void onFrameResult(int resultCode) {
        if (resultCode == 1) {
            P3Dir dir = (P3Dir) BaseEvent.getDefault().getParam();
            mPresenter.editFile(dir);
        }
    }


    private void execCommand(String command) {
        if (command.equals("")) {
            return;
        }
        String[] s = command.trim().split(" ");
        if (s.length > 3) {
            showMsg("命令有误");
            consoleField.setText("");
            return;
        }
        String key = s[0].toLowerCase();
        if (s.length == 1) {
            if (key.equals(Command.HELP)) {
                new HelpView();
                consoleField.setText("");
            } else {
                showMsg("命令有误");
            }
            return;
        }
        if (s.length == 3) {
            if (key.equals(Command.CHATTR)) {
                for (int i = 0; i < p3Dirs.size(); i++) {
                    if (p3Dirs.get(i).getName().equals(s[1])) {
                        try {
                            P3Dir newDir = (P3Dir) p3Dirs.get(i).clone();
                            if (newDir.getType() == FILE) {
                                currentFileIndex = i;
                                newDir.setAttr(s[2]);
                                mPresenter.editFile(newDir);
                            }
                            else
                                showMsg("不能编辑目录");
                            break;
                        } catch (CloneNotSupportedException e) {
                            e.printStackTrace();
                        }
                    }
                    if (i == p3Dirs.size() -1) {
                        showMsg("没有该文件");
                    }
                }
            } else {
                showMsg("命令有误");
            }
            return;
        }
        if (Command.hasKey(key)) {
            String value = s[1];
            if (key.equals(Command.CD)) {
                for (int i = 0; i < p3Dirs.size(); i++) {
                    P3Dir dir = p3Dirs.get(i);
                    if (dir.getName().equals(value)) {
                        inputPath = dir.getPath();
                        break;
                    }
                    if (i == p3Dirs.size() -1) {
                        inputPath = value;
                    }
                }
                mPresenter.getCurrentFile(inputPath);
                //null防止对正常访问造成影响
                inputPath = null;
                increasePathStack();
            } else if (key.equals(Command.MKDIR)) {
                mPresenter.createNewDir(currentPath, value);
            } else if (key.equals(Command.REMOVE)) {
                for (int i = 0; i < p3Dirs.size(); i++) {
                    if (p3Dirs.get(i).getName().equals(value)) {
                        currentFileIndex = i;
                        mPresenter.deleteFile(p3Dirs.get(i));
                        break;
                    }
                    if (i == p3Dirs.size() -1) {
                        showMsg("没有该文件");
                    }
                }
            } else if (key.equals(Command.TOUCH)) {
                mPresenter.createNewFile(currentPath, value);
            } else if (key.equals(Command.READ)) {
                for (int i = 0; i < p3Dirs.size(); i++) {
                    if (value.equals(p3Dirs.get(i).getName())) {
                        currentFileIndex = i;
                        if (p3Dirs.get(i).getType() == FILE) {
                            openFile(true);
                        } else {
                            showMsg("不能编辑目录");
                        }
                        break;
                    }
                    if (i == p3Dirs.size() -1) {
                        showMsg("没有该文件");
                    }
                }
            } else if (key.equals(Command.WRITE)) {
                for (int i = 0; i < p3Dirs.size(); i++) {
                    if (value.equals(p3Dirs.get(i).getName())) {
                        currentFileIndex = i;
                        if (p3Dirs.get(i).getType() == FILE) {
                            openFile(false);
                        } else {
                            showMsg("不能编辑目录");
                        }
                        break;
                    }
                    if (i == p3Dirs.size() -1) {
                        showMsg("没有该文件");
                    }
                }
            } else {
                showMsg("命令有误");
            }
        } else {
            showMsg("命令有误");
        }
        consoleField.setText("");
    }
}
